<html xmlns="http://www.w3.org/1999/xhtml" id="krank">

<head>
  <title>The KRANK Feature</title>
</head>

<body>
  <h1>The KRANK Feature</h1>
  
  <p>Laszlo Presentation Server versions 2.0 and above include a
  feature called <dfn>KRANK</dfn>, for optimizing the startup time of an
  application.  Krank allows you, without changing the source code, to
  construct an application that doesn't need to run any initialization
  code when it starts. <dfn>Kranking</dfn> an application thus can often
  result in a dramatic improvement in user-perceived startup time.</p>
  
  <h2>How to Krank a Laszlo application</h2>

<fixme>
This probably needs to go right up front:
Users should not krank in a deployed server, and they should not build
their apps to be kranked in a deployed environment. Users should ONLY
krank from their local dev machine to their own dev machine which is
only supported as their local server.
</fixme>

      <p>To use the KRANK feature:</p>
      
      <ol>
      <li> Make sure that  port 4444 is available on the LPS server. (It usually will be available unless your development client
      is on the other side of a firewall from the LPS server.  Consult your system administrator for problems with port
      availability.)</li>
      <li>Visit the application URL (for instance, <a target="_blank"
      href="../../examples/hello.lzx"><code>http://localhost:8080/lps-@VERSIONID@/examples/hello.lzx</code></a>),
      and click on the <i>Optimize</i> button at the lower right
      corner of the page.</li>

        <li> Wait while the Krank optimizations are performed; this
        may take several minutes (and sometimes more). The Krank
        optimization is a two step process: first data is gathered,
        and then new structures are built.  During the first phase LPS
        displays a static message, and in the second phase an elapsed
        time counter is updated every ten seconds.</li>

        <li>The server creates a kranked copy of the application
        and displays it. The kranked version, which has the same file name
        as the original application and an <code>.lzo</code>
        extension, is placed in the source directory that contains
        the <code>lzx</code> application source file.  To deploy a
        kranked application, copy the folder that contains this
        <code>lzo</code> file, and the lzx files and assets that the
        application uses, from the development server to the
        deployment server.</li>

        <li><p>For example if you kranked a file named
        <code>hello.lzx</code>, the kranked application would be
        called <code>hello.lzo</code>, and you would deploy it as you
        would any other Laszlo application. For example, if an HTML
        wrapper page for a Laszlo application includes the lines:</p>
<example executable="false" extract="false">
&lt;param name="movie" value="hello.lzx?lzt=swf"/&gt; <co>within the &lt;object&gt; tag</co>
&lt;embed src="hello.lzx?lzt=swf"&gt;</example>

        <p>simply change <code>hello.<i>lzx</i>?lzt=swf</code> to
        <code>hello.<i>lzo</i>?lzt=swf</code> to use the kranked
        version of the application.</p>
        </li>
      </ol>

      <h2>How it works</h2>
      
      <p>When a Laszlo application is loaded into a browser, there is
      a period of time before it can respond to user input, because it
      is running initialization code.  (This is the period when the
      splash resource is displayed, if the <code>&lt;splash&gt;</code>
      tag is present in the application.)</p>

      <p>An unkranked application contains code that creates views and
      performs other initializations every time the application is
      started.  The KRANK feature creates the views and performs this
      initialization once, and then builds a data structure that
      already contains these views and the results of performing these
      initializations. When you load a kranked application you do not
      need to wait for these views to be constructed and initialized;
      that has already been pre-computed during kranking.  Pre-computed
      operations include the construction of any views that are bound
      to static datasets (datasets that are baked into the
      application), and objects with no initstage attribute or an
      initstage of <code>early</code>, <code>normal</code>, or <code>late</code>.  Precomputed
      operations do NOT include the construction of replicated views
      that are bound to requested datasets; requested media resources;
      or objects marked with <code>initstage="deferred"</code>.</p>
      
      <h2>Application Code</h2>
      <p>In general, you do not need to modify the source of Laszlo
      applications according to whether they will be deployed as
      kranked or unkranked applications. However, there are certain
      cases in which an you may need to modify an application to
      insure that it works correctly when kranked.</p>
      
      <h3>Constraints, <code>init</code> methods, and
      <code>script</code> blocks</h3>
      
      <p>In an unkranked app, <code>$once</code> and
      <code>$immediately</code> constraints, <code>init</code>
      methods, and <code>script</code> blocks are executed after the
      application is loaded on the end user's machine.  In a kranked
      application, this code is executed on the developer's machine
      during the krank process.  The effect of this is that in a
      kranked application, calls in this code to retrieve load-time
      information such as query parameters and method of
      <code>LzBrowser</code> will return information about the URL
      that was used to krank the application, and about the machine
      that was used to krank the application.  In an unkranked
      application, these calls will return information about the URL
      that was used to load the application, and about the machine
      that the application is running on.</p>
      
      <h4>Example: Date</h4>
      <p>Unkranked, the following application displays the date and
      time at which it is loaded on the end user's machine.  Each time
      the application is loaded, it will display a different time.</p>

      <p>The kranked version of the same application will always
      display the same date and time: the time that it was kranked on
      the developer's machine.</p>

      <pre>&lt;canvas&gt;
  &lt;text text="$once{(new Date()).toString()}"/&gt;
&lt;/canvas&gt;</pre>

      <p>This difference also applies to <code>$immediately</code>
      constraints, and to the <classname>LzBrowser</classname> <code>get</code>
      functions.</p>

      <h4>Example: Constraint to query parameter</h4>

      <p>Unkranked, the following application displays the value of
      the <code>label</code> query parameter on the URL that is used
      to load it.  For example, if the application is requested from
      the URL
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/label.lzx?label=one</code>,
      it will display the text "one".  If it is requested from the URL
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/label.lzx?label=two</code>,
      it will display the text "two".</p>

      <p>Kranked, the application will always display the same label.
      This is the value of the query parameter on the URL that was
      used to krank it.  For example,
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/label.lzo?label=one</code>
      and
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/label.lzo?label=one</code>
      will display the same text.  (Note the use of <code>lzo</code>
      instead of <code>lzx</code> to request the kranked application.)
      If the application is kranked from the developer console, it
      will be kranked without a query parameter, and will always
      display the empty string.</p>
      
      <pre>&lt;canvas&gt;
  &lt;text text="$once{global.label}"/&gt;
&lt;/canvas&gt;</pre>

      <p>This distinction also applies to the use of constraints to
      initialize datasets; for example, <code>&lt;dataset name="ds"
      value="$once{global.url}"/&gt;</code>.</p>

      <h4>Example: Script that references query parameters</h4>
      <p>Similar to the previous case, the following fragment will
      initialize the variable <var>initialUrl</var> to the value of
      the <var>url</var> parameter that is used to <i>load</i> an
      unkranked application, but to the value that was used to
      <i>krank</i> a kranked application.</p>
      
      <pre>&lt;canvas&gt;
  &lt;script&gt;
    var initialUrl = global.url;
  &lt;/script;&gt;
  &lt;!-- &#x2026; --&gt;
&lt;/canvas&gt;</pre>

      <h3>"Baked-in" includes</h3>
      <p>An unkranked application that includes a file that changes
      periodically may be recompiled each time the file changes.
      (Whether it is recompiled depends on the value of the
      <code>compMgrDependencyOption</code> property of the
      <code>lps.properties</code> file.  See below.)  A kranked
      application is only recompiled when the developer explicitly
      does so.  The following application bakes in a copy of the file
      <code>data.xml</code>.  With the default development settings, a
      request to
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/baked.lzx</code>
      will always show the latest data in <code>data.xml</code>,
      because it will recompile the application if this data has
      changed since it was last compiled.  If the application is
      kranked, a request to
      <code>http://localhost:8080/lps-@VERSIONID@/my-apps/baked.lzo</code>
      will show the content of <code>data.xml</code> when the
      application was kranked, even if it has since been changed.</p>

      <pre>&lt;canvas&gt;
  &lt;dataset name="ds" src="data.xml"/&gt;
  &lt;text datapath="ds:/data/text()"/&gt;
&lt;/canvas&gt;</pre>

      <p>The solution is to use requested data, instead of baked-in
      data, if the data is expected to change more frequently than the
      application:</p>

      <pre>&lt;canvas&gt;
  &lt;dataset name="ds" src="http:data.xml" autorequest="true"/&gt;
  &lt;text datapath="ds:/data/text()"/&gt;
&lt;/canvas&gt;</pre>

      <p>This distinction between a kranked and an unkranked
      application is also true of baked-in media.  Only the unkranked
      application may be recompiled if <code>picture.jpg</code>
      changes, below.</p>
      
      <pre>&lt;canvas&gt;
  &lt;view resource="picture.jpg"/&gt;
&lt;/canvas&gt;</pre>

      <p>As with data, the solution is to use requested media:</p>

      <pre>&lt;canvas&gt;
  &lt;view resource="http:picture.jpg"/&gt;
&lt;/canvas&gt;</pre>


      <p>(Automatic recompilation depends on the value of the
      <code>compMgrDependencyOption</code> property of the
      <code>lps.properties</code> configuration file.  The default
      developer configuration sets this property to
      <code>check</code>, which causes the application to recompile.
      It is recommended that this flag be set to <code>never</code>
      for deployment, in order to maximize server capacity.  If this
      recommendation is followed, a kranked and an unkranked
      application will behave identically with respect to baked-in
      data.)</p>

      <h3>The <attribute>initstage</attribute> attribute</h3>
      <p>In an unkranked app, the canvas is initialized after
      <code>initstage="normal"</code> nodes but before <code>initstage="late"</code> nodes. In a
      kranked app, the canvas is initialized <em>after</em>
      <code>initstage="late"</code> nodes.</p>

      <p>This is necessary because <method>canvas.init</method> is defined to run when
      the app loads, yet krank instantiates all nodes except
      <code>initstage="defer"</code>, and this includes instantiating
      <code>initstage="late"</code> nodes.</p>

      <p>There is no reason to use <code>initstage="late"</code> in a kranked
      application, but if the application was initially optimized to
      run unkranked then this can come up.</p>
      
      <h2>Behavior of the <tagname>splash</tagname> tag in KRANKed applications.</h2>
      <p>
      In some cases the behavior of the <tagname>splash</tagname> element may differ in KRANKED and unKRANKed applications. </p>
<p>For example, if the <tagname>splash</tagname> <tagname>view</tagname> elements depend on the value of the <attribute>percentcreated</attribute> attribute, they will not work, because that attribute's value
is always 1 in a KRANKed application. The <attribute>percentcreated</attribute> attribute ends up at 1 in both KRANKed and unKRANKed applications.  The difference is that in a kranked application it never <i>changes</i> value, so an event handler for <attribute>onpercentcreated</attribute> will never be called.
</p>
<p>Sometimes, when loading a KRANKed application on to a relatively slow machine over a fast connection, you may not observe the "load-time" splash screen at all. 
To see why this is so, consider that there are two phases to splash: the <i>load</i> phase and the <i>initialize</i> phase. The "load-time splash screen is updated
during idle CPU cycles.</p>
<p>
Relative to an unKRANKed application, the load phase will generally take longer in a KRANKed application (because 
you are loading the "freeze-dried" object web) and the initialize phase is 'instantaneous' 
in a KRANKed application (because everything that would be trickle-created has already been created). </p>
<p> 
Thus in KRANKed applications screen updates may get dropped because the client machine's CPU
 is consumed by loading. Thus it is never idle, and so never does the splash update.  This behavior may vary from machine to machine and network
environment to network environment.</p>
<p>The problem for you as a developer, then, is to test your application's <tagname>splash</tagname> behavior in a variety of conditions. 
 You may need to simulate a non-local connection, by using a proxy server such as
 <a href="http://www.tcpiq.com/tcpiq/pwb/info.asp">Proxy Workbench</a> to throttle the connection speed. In cases where <tagname>splash</tagname>
behavior was apparently "broken" in a KRANKed application, we have found that
running the same application with the 
server throttled shows smooth updating of the load-time splash. 
</p>

      <h2>File sizes and performance</h2>
      
      <p>A kranked application will generally be larger than an
      unkranked application, and can be significantly larger (several
      times larger, or many kilobytes larger).  The relationship in
      size between an unkranked application and a kranked application
      depends upon the application.  If an application contains many
      statically replicated views, the kranked application will be
      significantly larger than the unkranked applications, because
      the kranked application will contain many instances of these
      views.  Among the sample applications, the Calendar application
      is a worst case for the KRANK feature, as far as size is
      concerned, because each day of the month is expanded out into a
      set of views and saved separately.  You can control the tradeoff
      between file size and initialization speed by marking views as
      initstage="deferred" and using the <method classname="LzNode">completeInstantiation</method> to force them to instantiate once the application is
      loaded, or by making datasets requested instead of static
      (e.g. changing <code>src="months.xml"</code> to <code>src="http:months.xml"</code>).</p>

      <p>Despite its larger file size, a Kranked application will
      often result in an improved user experience relative to the
      unkranked application.  This is because file download time
      accounts for only a portion of the time that must transpire
      before the user can interact with an application.  The rest of
      the time is taken by application initialization.  If downloading
      a kranked application takes, say, one second longer than
      downloaded the unkranked version, but the initialization time is
      many seconds faster, the user will perceive a faster startup
      time even though the file is larger.  Over a broadband
      connection even a much greater file size can be dwarfed by the
      increased initialization speed.  For example, even the worst
      case application, the Calendar, comes up faster over a local or
      high-speed broadband connection when kranked than when
      unkranked.</p>

      <p>Although kranking an application usually brings a benefit to
      the user, sometimes it does not.  In other words, sometimes the
      kranked version is no better than the unkranked
      version. Sometimes the performance improvement is obvious and
      dramatic; other times it's much more subtle.  The only good way
      to determine whether kranking an application is worthwhile is to
      do it and empirically measure the results.  At some future date,
      after we've collected more data and experience, we hope to
      provide heuristics to give you a sense of what to expect from
      kranking.</p>

      <h2>Memory requirements for development machine.</h2>

      <p>The KRANK feature requires more virtual and physical memory than other features of
      the Laszlo Presentation Server. Among the shipped examples, you
      may need to run Tomcat with a Java virtual memory setting of
    512MB, by setting the JVM option <code>-Xmx512m</code>.  In our experience at Laszlo
      Systems we have written applications, which use the Laszlo
      components, that require 300MB.  We recommend that you run on a
      development machine that has at least a gigabyte of physical memory.</p>

      <p>These memory requirements apply to the development machine
      that is used to create a kranked application.  The requirements
      for serving a kranked application are the same as those for the
      Laszlo Presentation Server in general; there is no additional
      overhead to serving a kranked application.</p>
      
      <note>
      Insufficient memory may cause the LPS to fail during kranking without an error message. 
      </note>

      <p>Because Kranking itself is compute-intensive and takes a lot
      of time, and because it does not require changes to source code,
      you should develop, debug and optimize you application before
      you krank it.  Kranking is an operation that should be done once
      your code is stable and you are preparing to deploy.</p>

<h2>Deploying KRANKED applications</h2>
<p>
The KRANK optimization process is designed to be the last thing done before a Laszlo application is released from your development group or function
to be tested and deployed. KRANKing should not be done on a server used for deploying Laszlo applications for general use. On the deployment server 
the ability to KRANK .lzx files should be disabled by editing the <code>lps.properties</code> file, as explained in 
<xref linkend="deployers-guide"><a href="${dguide}deployers-guide.html#lps.properties">Deploying Laszlo Applications</a></xref>. If you do not disable KRANK it will be possible
for users to overload the deployment machine by inadvertently or deliberately requesting KRANKing, which will dramatically reduce the 
server's performance, perhaps even crippling it.  This presents a security hole, as requesting KRANKing could thus be used for a DOS attack.
</p>

  </body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
